package org.example.uhy.domain.model.member;

import org.example.uhy.exceptions.IllegalParameterException;
import org.example.uhy.supports.meta.Aggregate;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 会员
 */
@Aggregate
public class Member {
    private MemberId memberId;
    private String name;
    private MemberLevelId levelId;
    private MemberLabel label;
    private Phone phone;
    private LocalDateTime createTime;
    private LocalDateTime upgradeTime;
    private LocalDateTime downgradeTime;
    // 已领用卡券数、可用卡券数放在会员上是否合适？

    private Member() {
    }

    public Member(MemberId memberId, String name, MemberLevelId levelId, Phone phone) {
        this.memberId(memberId);
        this.setName(name);
        this.levelId(levelId);
        this.phone(phone);
        createTime = LocalDateTime.now();
    }

    /**
     * 重新计算会员级别
     */
    public void calculateGrade() {
        // 降级的一些细节
        MemberLevelId newLevelId = null;
        this.levelId(newLevelId);
        this.upgradeTime = LocalDateTime.now();
        this.downgradeTime = LocalDateTime.now();
    }

    /**
     * 打标签
     *
     * @param label
     */
    public void mark(MemberLabel label) {
        this.label(label);
    }

    /**
     * 删除标签
     */
    public void unMark() {
        this.label = null;
    }

    /**
     * MemberId
     *
     * @return
     */
    public MemberId memberId() {
        return memberId;
    }

    // for constructor
    private void memberId(MemberId memberId) {
        if (memberId == null) {
            throw new IllegalParameterException("请输入会员ID");
        }
        this.memberId = memberId;
    }

    // for orm
    private String getId() {
        return memberId.getId();
    }

    // for orm
    private void setId(String memberId) {
        this.memberId = MemberId.of(memberId);
    }

    /**
     * Name
     *
     * @return
     */
    public String getName() {
        return name;
    }

    // for constructor, orm
    private void setName(String name) {
        if (name == null || name.length() == 0) {
            throw new IllegalParameterException("请输入会员姓名");
        }
        this.name = name;
    }

    /**
     * MemberLevelId
     *
     * @return
     */
    public MemberLevelId levelId() {
        return levelId;
    }

    private void levelId(MemberLevelId levelId) {
        if (levelId == null) {
            throw new IllegalParameterException("请输入会员级别");
        }
        this.levelId = levelId;
    }

    // for orm
    private String getLevelId() {
        return levelId.getId();
    }

    // for orm
    private void setLevelId(String levelId) {
        this.levelId = MemberLevelId.of(levelId);
    }

    /**
     * member label
     */
    public Optional<MemberLabel> label() {
        return Optional.ofNullable(label);
    }

    public boolean hasLabel() {
        return label != null;
    }

    private void label(MemberLabel label) {
        if (label == null) {
            throw new IllegalArgumentException("请输入会员标签");
        }
        this.label = label;
    }

    // for orm
    private String getLabel() {
        return label == null ? null : label.getLabel();
    }

    // for orm
    private void setLabel(String label) {
        if (label != null && label.length() > 0) {
            this.label = MemberLabel.of(label);
        }
    }

    /**
     * Phone
     *
     * @return
     */
    public Phone phone() {
        return phone;
    }

    // for constructor
    private void phone(Phone phone) {
        if (phone == null) {
            throw new IllegalParameterException("请输入会员手机号码");
        }
        this.phone = phone;
    }

    // for orm
    private String getPhone() {
        return phone.getPhone();
    }

    // for orm
    private void setPhone(String phone) {
        this.phone = new Phone(phone);
    }

    /**
     * createTime
     *
     * @return
     */
    private LocalDateTime getCreateTime() {
        return createTime;
    }

    private void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    /**
     * upgradeTime
     *
     * @return
     */
    public LocalDateTime getUpgradeTime() {
        return upgradeTime;
    }

    public void setUpgradeTime(LocalDateTime upgradeTime) {
        this.upgradeTime = upgradeTime;
    }

    /**
     * downgradeTime
     *
     * @return
     */
    public LocalDateTime getDowngradeTime() {
        return downgradeTime;
    }

    public void setDowngradeTime(LocalDateTime downgradeTime) {
        this.downgradeTime = downgradeTime;
    }
}
